package com.bidevalution.service.impl;

import com.bidevalution.core.Common;
import com.bidevalution.core.constant.CharConstant;
import com.bidevalution.core.constant.LocalPathConstant;
import com.bidevalution.core.enums.ApiEnum;
import com.bidevalution.core.enums.FileStatusEnum;
import com.bidevalution.core.enums.FileTypeEnum;
import com.bidevalution.core.util.DesUtil;
import com.bidevalution.core.util.HttpClientUtil;
import com.bidevalution.core.util.WebServiceUtils;
import com.bidevalution.dao.ApiBidFileMapper;
import com.bidevalution.model.BidFile;
import com.qtp.core.common.HttpTookit;
import com.qtp.core.model.Response;
import com.qtp.core.util.Base64Util;
import com.qtp.core.util.GsonUtil;
import com.qtp.core.util.OConvertUtils;
import com.qtp.core.util.XmlUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @author huyiqi
 * @date 2019/11/11
 */
class BaseServiceImpl {

    private static final Logger log = LoggerFactory.getLogger(BaseServiceImpl.class);

    static final Integer API_TYPE_JY = 0;
    static final Integer API_TYPE_FX = 1;

    /**
     *建易接口 返回信息的根節點和執行結果節點
     */
    private static final String JY_XML_ROOT_NAME = "NewDataSet";
    private static final String JY_XML_EXEC_RESULT_NAME = "ExecResult";

    /**
     * 方欣專家驗證接口 返回信息的根節點和執行結果節點
     */
    private static final String FX_XML_ROOT_NAME = "GetExportInfoByCardIDNameResult";
    private static final String FX_XML_EXEC_RESULT_NAME = "error";

    private static final String SUCCESS_STR = "![CDATA[1]]";

    private static final String RESULT_IS_EMPTY = "结果集为空";

    /**
     * 調用建易webservice接口
     * @param api 接口類型
     * @param params 參數
     * @return 返回調用結果
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    Map<String, Object> invokeJyWebService(ApiEnum api, String... params) throws Exception {
        log.info("======调用建易webservice开始======");
        log.info("======调用URL："+api.getUrl()+"======");
        log.info("======调用方法："+api.getMethod()+"======");
        log.info("======调用参数："+StringUtils.join(params, ",")+"======");
        Map<String, Object> resultMap = null;
        if(params.length > 1) {
            for(int i=1; i<params.length; i++) {
                params[i] = DesUtil.encrypt(params[i], api.getDesKey(), api.getDesIv());
            }
        }
        String result = WebServiceUtils.callWebSV(api.getUrl(), api.getMethod(), params);
        log.info("======返回值："+result+"======");
        if(StringUtils.isNotBlank(result)) {
            String xml;
            if(result.contains(JY_XML_ROOT_NAME)) {
                xml = result;
            } else {
                xml = DesUtil.decrypt(result, api.getDesKey(), api.getDesIv());
                log.info("======解密后的值："+xml+"======");
            }
            resultMap = XmlUtil.xml2map(xml, true);
        }
        log.info("======调用建易webservice结束======");
        return resultMap;
    }
    Map<String, Object> invokeJyWebServiceWithGbkResult(ApiEnum api, String... params) throws Exception {
        log.info("======调用建易webservice开始======");
        log.info("======调用URL："+api.getUrl()+"======");
        log.info("======调用方法："+api.getMethod()+"======");
        log.info("======调用参数："+StringUtils.join(params, ",")+"======");
        Map<String, Object> resultMap = null;
        if(params.length > 1) {
            for(int i=1; i<params.length; i++) {
                params[i] = DesUtil.encrypt(params[i], api.getDesKey(), api.getDesIv());
            }
        }
        String result = WebServiceUtils.callWebSV(api.getUrl(), api.getMethod(), params);
        log.info("======返回值："+result+"======");
        if(StringUtils.isNotBlank(result)) {
            String xml;
            if(result.contains(JY_XML_ROOT_NAME)) {
                xml = result;
            } else {
                xml = DesUtil.decrypt(result, api.getDesKey(), api.getDesIv(), "UTF-8");
                log.info("======解密后的值："+xml+"======");
            }
            resultMap = XmlUtil.xml2map(xml, true);
        }
        log.info("======调用建易webservice结束======");
        return resultMap;
    }
    @SuppressWarnings("unchecked")
    Map<String, Object> invokeJyWebServiceBase64(ApiEnum api, String... params) throws Exception {
        log.info("======调用建易webservice开始======");
        log.info("======调用URL："+api.getUrl()+"======");
        log.info("======调用方法："+api.getMethod()+"======");
        log.info("======调用参数："+StringUtils.join(params, ",")+"======");
        Map<String, Object> resultMap = null;
        if(params.length > 1) {
            for(int i=1; i<params.length; i++) {
                params[i] = new String(Base64.encodeBase64(params[i].getBytes("GB2312")));
            }
        }
        String result = WebServiceUtils.callWebSV(api.getUrl(), api.getMethod(), params);
        log.info("======返回值："+result+"======");
        if(StringUtils.isNotBlank(result)) {
            String xml;
            if(result.contains(JY_XML_ROOT_NAME)) {
                xml = result;
                resultMap = XmlUtil.xml2map(xml, true);
            }
        }
        log.info("======调用建易webservice结束======");
        return resultMap;
    }

    @SuppressWarnings("unchecked")
    Map<String, Object> invokeFxWebService(ApiEnum api, String... params) throws Exception {
        log.info("======调用方欣webservice开始======");
        log.info("======调用URL："+api.getUrl()+"======");
        log.info("======调用方法："+api.getMethod()+"======");
        log.info("======调用参数："+StringUtils.join(params, ",")+"======");
        Map<String, Object> resultMap = null;
        String result = WebServiceUtils.callWebSV(api.getUrl(), api.getMethod(), params);
        log.info("======返回值："+result+"======");
        if(StringUtils.isNotBlank(result) && result.contains(FX_XML_ROOT_NAME)) {
            resultMap = XmlUtil.xml2map(result, true);
        }
        log.info("======调用方欣webservice结束======");
        return resultMap;
    }

    /**
     * 解析建易api返回的結果
     * @param resultMap 返回的信息
     * @return 返回調用是否成功
     */
    @SuppressWarnings("unchecked")
    Response<Map<String, Object>> jYApiSuccess(Map<String, Object> resultMap) {
        if(resultMap != null) {
            Map<String, Object> dataSet = (Map<String, Object>) resultMap.get(JY_XML_ROOT_NAME);
            if(dataSet != null) {
                Map<String, Object> execResult = (Map<String, Object>) dataSet.get(JY_XML_EXEC_RESULT_NAME);
                if(execResult != null) {
                    String execSucc = OConvertUtils.getString(execResult.get("ExecSuccessfully"));
                    if(StringUtils.isNotBlank(execSucc) && execSucc.contains(SUCCESS_STR)) {
                        return Response.ok(dataSet);
                    }
                    int success = OConvertUtils.getInt(execSucc, 0);
                    if(success == 1) {
                        return Response.ok(dataSet);
                    } else {
                        String description = OConvertUtils.getString(execResult.get("Description"));
                        return Response.fail(description);
                    }
                }
            }
        }
        return Response.fail(RESULT_IS_EMPTY);
    }

    @SuppressWarnings("unchecked")
    Response<Map<String, Object>> fXApiSuccess(Map<String, Object> resultMap) {
        //todo 如何判断方欣结果
        if(resultMap != null) {
            Map<String, Object> dataSet = (Map<String, Object>) resultMap.get(FX_XML_ROOT_NAME);
            if(dataSet != null) {
                Map<String, Object> execResult = (Map<String, Object>) dataSet.get(FX_XML_EXEC_RESULT_NAME);
                if(execResult != null) {
                    int success = OConvertUtils.getInt(execResult.get("ID"), 1);
                    if(success == 0) {
                        return Response.ok(dataSet);
                    } else {
                        String description = OConvertUtils.getString(execResult.get("Describe"));
                        Response.fail(description);
                    }
                }
            }
        }
        return Response.fail(RESULT_IS_EMPTY);
    }

    /**
     * 調用T9的接口
     * @param api 接口
     * @param params 參數
     * @return 返回調用結果
     * @throws Exception
     */
    Map<String, Object> invokeHttpApi(ApiEnum api, Map<String, String> params) throws Exception {
        log.info("======调用T9接口开始======");
        Map<String, Object> resultMap = null;
        //请求地址
        StringBuilder url = new StringBuilder(api.getUrl());
        String method = api.getMethod();
        url.append(method);
        url.append("?");
        Set<Map.Entry<String, String>> entries = params.entrySet();
        for(Map.Entry<String, String> entry:entries) {
            url.append(entry.getKey()).append("=").append(entry.getValue());
            url.append("&");
        }
        log.info("======调用URL："+url.toString()+"======");
        //执行
        String result = HttpClientUtil.doGet(url.toString());
        log.info("======返回值："+result+"======");
        //解析结果
        if(isJson(result)) {
            resultMap = GsonUtil.jsonToMapWithGson(result);
        }
        log.info("======调用T9接口结束======");
        return resultMap;
    }

    Map<String, Object> invokeHttpApiPost(ApiEnum api, Map<String, Object> params) throws Exception {
        log.info("======调用T9接口开始======");
        Map<String, Object> resultMap = null;
        //请求地址
        StringBuilder url = new StringBuilder(api.getUrl());
        String method = api.getMethod();
        url.append(method);
        log.info("======调用URL："+url.toString()+"======");
        //执行
        String result = HttpTookit.sendPost(url.toString(), params);
        log.info("======返回值："+result+"======");
        //解析结果
        if(isJson(result)) {
            resultMap = GsonUtil.jsonToMapWithGson(result);
        }
        log.info("======调用T9接口结束======");
        return resultMap;
    }

    /**
     * 解析T9返回的結果
     * @param resultMap 返回的結果
     * @return 返回調用是否成功
     */
    Response<String> t9ApiSuccess(Map<String, Object> resultMap) {
        if(resultMap != null) {
            int code = OConvertUtils.getInt(resultMap.get("code"));
            if(code == HttpStatus.SC_OK) {
                return Response.ok();
            } else {
                return Response.fail("調用失败");
            }
        }
        return Response.fail(RESULT_IS_EMPTY);
    }

    Response<String> returnExecResult(Map<String, Object> resultMap, Integer type) {
        if(resultMap != null) {
            Response<Map<String, Object>> execResult;
            if(API_TYPE_JY.equals(type)) {
                execResult = jYApiSuccess(resultMap);
            } else {
                execResult = fXApiSuccess(resultMap);
            }
            if (execResult.isSuccess()) {
                return Response.ok();
            } else {
                return Response.fail(execResult.getError());
            }
        }
        return Response.fail("接口返回值为空");
    }


    /**
     * 從路徑中提取文件名
     * @param filePath 文件路徑
     * @return 返回文件名稱
     */
    String getFileName(String filePath) {
        String fileName = "";
        if(StringUtils.isNotBlank(filePath)) {
            String[] addr = filePath.split("/");
            if(addr.length > 0) {
                fileName = addr[addr.length - 1];
            }
        }
        return fileName;
    }

    /**
     * 獲取投標文件保存路徑
     * @param filePath 相對路徑
     * @return 返回絕對路徑
     */
    String getFtpFilePath(String filePath) {
        return Common.splicePath(LocalPathConstant.TB_FILE_PATH, filePath);
    }

    /**
     * 保存文件操作表
     * @param fileName 文件名稱
     * @param ftpFilePath 文件路徑
     * @param fileType 文件类型
     * @param bidFileMapper bidFileMapper
     */
    String saveBidFile(String fileName, String ftpFilePath, String entId, int fileType, String sectionCode, int status, ApiBidFileMapper bidFileMapper) {
        log.info("查询文件操作表，ftpFilePath："+ftpFilePath);
        BidFile bidFile = bidFileMapper.findBidFileByPath(ftpFilePath);
        String fileId;
        if(bidFile==null) {
            fileId = UUID.randomUUID().toString();
            log.info("没有查询到，准备插入，参数：fileId,fileName,filePath,fileType,status,bidEntId,createtime,modifytime,parentId");
            Date now = new Date();
            Map<String, Object> map = new HashMap<>(16);
            map.put("fileId", fileId);
            map.put("fileName", fileName);
            map.put("filePath", ftpFilePath);
            map.put("fileType", fileType);
            map.put("status", status);
            map.put("bidEntId", entId);
            map.put("createTime", now);
            map.put("modifyTime", now);
            map.put("parentId", "0");
            map.put("projCode", sectionCode);
            log.info(fileId+","+fileName+","+ftpFilePath+","+fileType+","+status+","+entId+","+now+","+now+",0");
            bidFileMapper.insert(map);
            log.info("插入成功");
        } else {
            fileId = bidFile.getFileId();
            log.info("已有记录，不插入");
        }
        return fileId;
    }

    /**
     * 判断是否是json格式的字符串
     * @param jsonStr 字符串
     * @return 返回结果
     */
    private boolean isJson(String jsonStr) {
        return StringUtils.isNotBlank(jsonStr) && (isArrayJson(jsonStr) || isObjectJson(jsonStr));
    }

    boolean isArrayJson(String jsonStr) {
        if(StringUtils.isNotBlank(jsonStr)) {
            return jsonStr.startsWith(CharConstant.CHAR_ARRAY_BEGIN)
                    && jsonStr.endsWith(CharConstant.CHAR_ARRAY_END);
        }
        return false;
    }

    boolean isObjectJson(String jsonStr) {
        if(StringUtils.isNotBlank(jsonStr)) {
            return jsonStr.startsWith(CharConstant.CHAR_OBJECT_BEGIN)
                    && jsonStr.endsWith(CharConstant.CHAR_OBJECT_END);
        }
        return false;
    }

}
